<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ajax-upload</title>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.css" rel="stylesheet">
    <style>
        .progress-area {
            padding: 20px;
        }
    </style>
</head>
<body>
<div class="">
    <p>文件上传</p>
    <div>
        <input type="file" name="file" id="file" />
        <div>
            <p>图片预览（如果上传文件时图片）</p>
            <div class="img-preview">
            </div>
        </div>
        <button id="upload">上传</button>
        <button id="btn">终止上传</button>
        <div class="progress-area">
            进度
            <div class="progress">
                <div class="progress-bar" id="progress" role="progressbar"  aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">0%</div>
            </div>
            <div>
                <p id="time"></p>
            </div>
        </div>
    </div>
</div>
<script>
    (function () {
        'use strict';
        var file = document.querySelector('#file');
        var upload = document.querySelector('#upload');
        var progress = document.querySelector('#progress');
        var time = document.querySelector('#time');
        var imgPreview = document.querySelector('.img-preview');
        var xhr = new XMLHttpRequest();
        var loaded = 0, ot = 0, total = 0, oloaded = 0 ;//;
        upload.addEventListener('click', uploadFile, false);
        file.addEventListener('change', previewImage, false);
        // 点击上传
        function uploadFile(event) {
            if(!file.files[0]) {
                alert('请选择文件')
                return
            }
            if(file.files[0].size>1000000000) {
                alert('文件不得超过1000M')
                return
            }
            var formData = new FormData();
            formData.append('file', file.files[0]);
            xhr.onload = uploadSuccess;
            xhr.upload.onprogress = setProgress;
            xhr.open('post', '/ajax_upload', true);
            xhr.send(formData);
        }
        // 成功上传
        function uploadSuccess(event) {
            if (xhr.readyState === 4 && xhr.status === 200) {
                setTimeout(()=> {
                    alert('上传成功')
                    window.location.reload();
                },1000)
            }
        }
        // 进度条
        function setProgress(event) {
            // event.total是需要传输的总字节，event.loaded是已经传输的字节。如果event.lengthComputable不为真，则event.total等于0
            if (event.lengthComputable) {//
                loaded = event.loaded
                total = event.total
                var complete = (event.loaded / event.total * 100).toFixed(1);
                progress.innerHTML = Math.round(complete) + "%";
                progress.style.width = complete + '%';
            }
            var time = document.getElementById("time");
            var nt = new Date().getTime();//获取当前时间
            var pertime = (nt-ot)/1000; //计算出上次调用该方法时到现在的时间差，单位为s
            ot = new Date().getTime(); //重新赋值时间，用于下次计算
            var perload = event.loaded - oloaded; //计算该分段上传的文件大小，单位b
            oloaded = event.loaded;//重新赋值已上传文件大小，用以下次计算
            //上传速度计算
            var speed = perload/pertime;//单位b/s
            var bspeed = speed;
            var units = 'b/s';//单位名称
            if(speed/1024>1){
                speed = speed/1024;
                units = 'k/s';
            }
            if(speed/1024>1){
                speed = speed/1024;
                units = 'M/s';
            }
            speed = speed.toFixed(1);
            //剩余时间
            var resttime = ((event.total-event.loaded)/bspeed).toFixed(1);
            time.innerHTML = '传输速度：'+speed+units+'，剩余时间：'+resttime+'s';
            // if(bspeed==0) time.innerHTML = '上传已取消';
        }
        // 图片预览
        function previewImage(event) {
            imgPreview.innerHTML = ''
            // 每次重新选择文件的时候，都会去除上次选择产生的img标签
            var isImg = (event.target.files[0].type).indexOf('image/') > -1;
            if(isImg) {
                // 如果是图片 就解析图片预览
                var img = document.createElement('img')
                imgPreview.appendChild(img)
                var reader = new FileReader();
                reader.onload = function (event) {
                    img.src = event.target.result;
                    img.width = '200'
                };
                reader.readAsDataURL(event.target.files[0]);
            } else {
                // imgPreview.appendChild('<img src=""/>')
                // 可以为非图片文件选择一个默认的文件logo
            }
        }
        //++++++++++++++++++++++++++++++++++++++++++++
        xhr.onloadstart = function(){
            console.log("上传开始");
        }
        btn.onclick = function(){
            xhr.abort();
            console.log("上传被终止.");
            progress.style.width = 0 + '%';
            progress.innerHTML = 0 + '%';
            // 这里调用取消上传的代码
        };
        xhr.ontimeout = function(){
            console.log('上传超时.');
        }
        // xhr.timeout = 50000; // 默认为0 没有时间限制
        // xhr.onabort = function(){
        //   console.log("The transfer has been canceled by the user.");
        // }
        xhr.onerror = function(){
            console.log("上传错误，可能是断网了，也可能是断请求服务了.");  // 这里存在异步传输问题
            return
        }
        xhr.onloadend = function(){
            console.log("请求结束"); // 发送上传的请求，至于有没有上传成功，不清楚，可能失败 成功，这里只是请求结束了
        }
        // +++++++++++++++++++++++++++++++++++++++++++
    })();
</script>
</body>
</html>